use std::borrow::Borrow;
use std::cell::RefCell;
use std::rc::{Rc, Weak};

// crate关键字，绝对路径引入，从包根开始;
// 在这里就是从当前文件引入List枚举的Cons和Nil变体，也就简化了直接使用是繁琐的List::Cons和List::Nil写法，这样就加强了代码的可读性
use crate::List::{Cons, Nil};

// 递归类型，通过Box智能指针来实现，因为List无法获取自身的大小，栈上的空间有限，所以需要使用堆上的空间
// enum List {
//     Cons(i32, Box<List>),
//     Nil,
// }

// 递归类型，通过Rc智能指针实现，Rc具有多重所有权，引用可拥有多个所有者，当最后一个所有者断开引用，将被释放
// enum List {
//     Cons(i32, Rc<List>),
//     Nil,
// }

// 递归类型，通过Rc智能指针+RefCell智能指针实现，让Cons值可修改
#[derive(Debug)]
enum List {
    Cons(Rc<RefCell<i32>>, Rc<List>),
    Nil,
}

// 需求，实现一个track跟踪消息发送值与最大值，在不同状态给出提示
trait Messenger {
    fn send(&self, msg: &str);
}

struct LimitTracker<'a, T: Messenger> {
    message: &'a T,
    value: usize,
    max: usize,
}

impl<'a, T> LimitTracker<'a, T>
where
    T: Messenger,
{
    fn new(message: &'a T, max: usize) -> LimitTracker<'a, T> {
        LimitTracker {
            message,
            value: 0,
            max,
        }
    }

    fn set_value(&mut self, value: usize) {
        self.value = value;
        let percentage_of_max = self.value as f64 / self.max as f64;
        if percentage_of_max >= 1.0 {
            self.message.send("错误：你已经超出你的配额限制！")
        } else if percentage_of_max >= 0.9 {
            self.message.send("紧急警告：快要超出你的配额限制了！")
        } else if percentage_of_max >= 0.75 {
            self.message.send("警告：你已经超出75%配额限制了！")
        }
    }
}

#[derive(Debug)]
struct MockMessenger {
    // 第一种写法，直接用Vec!存放消息
    // sent_messages: Vec<String>,
    // 第二种写法，改进上述方式
    sent_messages: RefCell<Vec<String>>,
}

impl MockMessenger {
    fn new() -> MockMessenger {
        MockMessenger {
            sent_messages: RefCell::new(vec![]),
        }
    }
}

impl Messenger for MockMessenger {
    fn send(&self, msg: &str) {
        // 用向量来存消息，不符合Messenger特质的设计，借用不可变引用，目的隔离Message类型和LimitTracker类型，力求彼此独立
        // self.sent_messages.push(String::from(msg));
        // 通过RefCell<T>智能指针，调用borrow_mut方法运用内部可变性，内部值可变引用进行修改，且避开编译时借用规则检查，推至运行时进行借用规则检查，
        self.sent_messages.borrow_mut().push(String::from(msg));
    }
}

// Weak智能指针处理循环引用的应用场景
#[derive(Debug)]
struct Node {
    value: i32,
    parent: RefCell<Weak<Node>>,
    children: RefCell<Vec<Rc<Node>>>,
}

fn main() {
    // Box
    // let l1 = Cons(3, Box::new(Cons(2, Box::new(Cons(1, Box::new(Nil))))));

    // Rc
    // 需求：创建l2和l3，同时引用l1作为List值
    // 以下方式，是错误示范，当l1被传入Box::new时，所有权被转移，因此在l3中就不能继续使用l1
    // let l1 = Rc::new(Cons(3, Rc::new(Cons(2, Rc::new(Cons(1, Rc::new(Nil)))))));
    // println!("count creating a = {}", Rc::strong_count(&l1));

    // let l2 = Cons(4, Box::new(l1));
    // let l3 = Cons(5, Box::new(l1));

    // 以下方式，就通过Rc多重所有权实现了，l2和l3共用同一段l1数据
    // let l2 = Cons(4, Rc::clone(&l1));
    // let l3 = Cons(5, Rc::clone(&l1));
    // println!("count creating a = {}", Rc::strong_count(&l1));

    // {
    //     // Rc类型的强引用在，作用域结束后将被解除，可以从以下打印中观察到
    //     // 当所有强引用被解除后，Rc类型值将被释放
    //     let l4 = Cons(6, Rc::clone(&l1));
    //     println!("count creating a = {}", Rc::strong_count(&l1));
    // }
    // println!("count creating a = {}", Rc::strong_count(&l1));

    // RefCell
    it_sends_an_over_75_percent_waring_message();

    // Rc + RefCell
    let value = Rc::new(RefCell::new(5));

    let a = Rc::new(Cons(Rc::clone(&value), Rc::new(Nil)));
    let b = Cons(Rc::new(RefCell::new(1)), Rc::clone(&a));
    let c = Cons(Rc::new(RefCell::new(3)), Rc::clone(&a));

    // 通过RefCell进行内部值可变修改
    *value.borrow_mut() += 10;

    println!("{:?}", a);
    println!("{:?}", b);
    println!("{:?}", c);

    // Weak
    let leaf = Rc::new(Node {
        value: 1,
        parent: RefCell::new(Weak::new()),
        children: RefCell::new(vec![]),
    });
    println!("子叶节点的父节点: {:?}", leaf.parent.borrow().upgrade());

    // 弱引用与作用域关系，和强引用一样，超出作用域将会被解除
    let branch = Rc::new(Node {
        value: 5,
        parent: RefCell::new(Weak::new()),
        children: RefCell::new(vec![Rc::clone(&leaf)]),
    });
    *leaf.parent.borrow_mut() = Rc::downgrade(&branch);
    println!("子叶节点的父节点: {:?}", leaf.parent.borrow().upgrade());

    let leaf = Rc::new(Node {
        value: 1,
        parent: RefCell::new(Weak::new()),
        children: RefCell::new(vec![]),
    });
    println!(
        "子节点 强引用={} 弱引用={}",
        Rc::strong_count(&leaf),
        Rc::weak_count(&leaf)
    );

    {
        let branch = Rc::new(Node {
            value: 3,
            parent: RefCell::new(Weak::new()),
            children: RefCell::new(vec![Rc::clone(&leaf)]),
        });
        *leaf.parent.borrow_mut() = Rc::downgrade(&branch);
        println!(
            "父节点 强引用={} 弱引用={}",
            Rc::strong_count(&branch),
            Rc::weak_count(&branch)
        );
        println!(
            "子节点 强引用={} 弱引用={}",
            Rc::strong_count(&leaf),
            Rc::weak_count(&leaf)
        );
    }
    println!(
        "子节点 强引用={} 弱引用={}",
        Rc::strong_count(&leaf),
        Rc::weak_count(&leaf)
    );
    println!("子节点的父节点 {:?}", leaf.parent.borrow().upgrade())
}

fn it_sends_an_over_75_percent_waring_message() {
    let mock_messenger = MockMessenger::new();
    let mut limit_tracker = LimitTracker::new(&mock_messenger, 100);

    limit_tracker.set_value(75);
    limit_tracker.set_value(100);
    println!("{:?}", mock_messenger);
}
